"""
Flask 应用工厂模块
"""

from flask import Flask
from flask_cors import CORS
from flask_socketio import SocketIO
from pymongo import MongoClient
from redis import Redis
from .config import Config
import logging
from pathlib import Path


# 全局对象
mongo_client = None
mongo_db = None
redis_client = None
socketio = None


def create_app(config_class=Config):
    """
    Flask 应用工厂函数
    
    Args:
        config_class: 配置类
        
    Returns:
        Flask: Flask应用实例
    """
    app = Flask(__name__)
    app.config.from_object(config_class)
    
    # 初始化扩展
    init_extensions(app)
    
    # 注册蓝图
    register_blueprints(app)
    
    # 配置日志
    configure_logging(app)
    
    # 创建必要的目录
    create_directories(app)
    
    return app


def init_extensions(app):
    """
    初始化Flask扩展
    
    Args:
        app: Flask应用实例
    """
    global mongo_client, mongo_db, redis_client, socketio
    
    # 初始化CORS
    CORS(app, resources={
        r"/api/*": {
            "origins": app.config.get('CORS_ORIGINS', ['http://localhost:5173']),
            "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
            "allow_headers": ["Content-Type", "Authorization"]
        }
    })
    
    # 初始化SocketIO
    socketio = SocketIO(
        app,
        cors_allowed_origins=app.config.get('CORS_ORIGINS', ['http://localhost:5173']),
        async_mode='threading',
        logger=app.config.get('DEBUG', False),
        engineio_logger=app.config.get('DEBUG', False)
    )
    
    # 初始化MongoDB
    try:
        mongo_client = MongoClient(app.config['MONGO_URI'])
        mongo_db = mongo_client.get_default_database()
        
        # 测试连接
        mongo_client.admin.command('ping')
        app.logger.info("MongoDB连接成功")
        
    except Exception as e:
        app.logger.error(f"MongoDB连接失败: {str(e)}")
        if not app.config.get('TESTING'):
            raise
    
    # 初始化Redis
    try:
        redis_client = Redis.from_url(app.config['REDIS_URL'])
        
        # 测试连接
        redis_client.ping()
        app.logger.info("Redis连接成功")
        
    except Exception as e:
        app.logger.error(f"Redis连接失败: {str(e)}")
        if not app.config.get('TESTING'):
            raise


def register_blueprints(app):
    """
    注册蓝图
    
    Args:
        app: Flask应用实例
    """
    from .api.upload import upload_bp
    from .api.task import task_bp
    from .api.download import download_bp
    from .api.websocket import websocket_bp
    
    # 注册API蓝图
    app.register_blueprint(upload_bp, url_prefix='/api')
    app.register_blueprint(task_bp, url_prefix='/api')
    app.register_blueprint(download_bp, url_prefix='/api')
    app.register_blueprint(websocket_bp)


def configure_logging(app):
    """
    配置日志
    
    Args:
        app: Flask应用实例
    """
    if not app.config.get('TESTING'):
        # 配置日志格式
        logging.basicConfig(
            level=app.config.get('LOG_LEVEL', logging.INFO),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.StreamHandler(),
                logging.FileHandler(
                    app.config.get('LOG_FILE', 'app.log'),
                    encoding='utf-8'
                )
            ]
        )
        
        # 设置第三方库日志级别
        logging.getLogger('werkzeug').setLevel(logging.WARNING)
        logging.getLogger('socketio').setLevel(logging.WARNING)
        logging.getLogger('engineio').setLevel(logging.WARNING)


def create_directories(app):
    """
    创建必要的目录
    
    Args:
        app: Flask应用实例
    """
    directories = [
        app.config['UPLOAD_FOLDER'],
        app.config['OUTPUT_FOLDER'],
        app.config['TEMP_FOLDER']
    ]
    
    for directory in directories:
        Path(directory).mkdir(parents=True, exist_ok=True)
        app.logger.info(f"确保目录存在: {directory}")


# 导出全局对象供其他模块使用
def get_mongo_db():
    """获取MongoDB数据库实例"""
    return mongo_db


def get_redis_client():
    """获取Redis客户端实例"""
    return redis_client


def get_socketio():
    """获取SocketIO实例"""
    return socketio